package com.itany.corejava.code15_stream;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author 石小俊
 * @date 2023年05月31日 13:51
 */
public class Test03_终止操作 {

    private static List<Integer> list = Arrays.asList(5, 3, 12, 21, 9, 2, 25, 1, 5, 3);

    public static void main(String[] args) {
        allMatchTest();
        anyMatchTest();
        noneMatchTest();
        findFirstTest();
        findAnyTest();
        countTest();
        maxTest();
        minTest();
        reduceTest();
        collectTest();
    }

    public static void allMatchTest() {
        // Stream中可以不定义中间操作
        boolean flag = list.stream()
                // 检查流中所有元素是否都比2大,只要有任意一个不比2大则返回false
                .allMatch(i -> i > 2);
        System.out.println("集合中所有元素是否都是正数:" + flag);
    }

    public static void anyMatchTest() {
        // Stream中可以不定义中间操作
        boolean flag = list.stream()
                // 检查流中所有元素是否存在比2大的数,只要有任意一个比2大则返回true
                .anyMatch(i -> i > 2);
        System.out.println("集合中所有元素是否都是正数:" + flag);
    }

    public static void noneMatchTest() {
        // Stream中可以不定义中间操作
        boolean flag = list.stream()
                // 所有元素都不满足,则返回true
                .noneMatch(i -> i < 0);
        System.out.println("集合中所有元素是否都是正数:" + flag);
    }

    public static void findFirstTest() {
        list = new ArrayList<>();
        Optional<Integer> first = list.stream().findFirst();
        // 直接取出容器中的值,如果没有值会抛出异常
        // System.out.println(first.get());
        // 可以通过判断获取对应的值
        // 判断容器中是否有值,有值则取出来,没值可以设置一个默认值
        if (first.isPresent()) {
            // 如果有值
            Integer num = first.get();
            System.out.println(num);
        } else {
            // 如果没有值,可以为其设置一个默认值
            Integer num = first.orElse(0);
            System.out.println(num);
        }

    }

    public static void findAnyTest() {
        Optional<Integer> any = list.stream().findAny();
        System.out.println("当前线程:" + any.get());
        Optional<Integer> any2 = list.stream().findAny();
        System.out.println("当前线程:" + any2.get());
        Optional<Integer> any3 = list.stream().findAny();
        System.out.println("当前线程:" + any3.get());
        Optional<Integer> any4 = list.stream().findAny();
        System.out.println("当前线程:" + any4.get());

        new Thread() {
            @Override
            public void run() {
                Optional<Integer> any = list.parallelStream().findAny();
                System.out.println("多线程:" + any.get());
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                Optional<Integer> any = list.parallelStream().findAny();
                System.out.println("多线程:" + any.get());
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                Optional<Integer> any = list.parallelStream().findAny();
                System.out.println("多线程:" + any.get());
            }
        }.start();
    }

    public static void countTest() {
        long count = list.stream().count();
        System.out.println("流中元素的数量:" + count);
    }

    public static void maxTest() {
        Optional<Integer> max = list.stream().max((a, b) -> a - b);
        System.out.println(max.get());
        Optional<Integer> max2 = list.stream().min((a, b) -> b - a);
        System.out.println(max2.get());
    }

    public static void minTest() {
        // 可以通过max比较后取出最小的值
        Optional<Integer> min1 = list.stream().max((a, b) -> b - a);
        System.out.println(min1.get());
        Optional<Integer> min2 = list.stream().min((a, b) -> a - b);
        System.out.println(min2.get());
    }

    public static void reduceTest() {
        // 返回集合中所有元素之和
        // 其参数是BinaryOperator,属于函数式接口,且是BiFunction子类
        // 方法:R apply(T t, U u);
        // 在Integer中提供了一个静态方法sum,用于求两数之和
        // 此处也可以通过调用Integer中的静态方法sum来实现
        // Optional<Integer> reduce = list.stream().reduce((a, b) -> a + b);
        Optional<Integer> reduce = list.stream().reduce(Integer::sum);
        System.out.println(reduce.get());

        // 1~100之间整数之和
        Optional<Integer> reduce2 = Stream.iterate(1, i -> i + 1)
                .limit(100)
                // .reduce((a, b) -> a + b);
                .reduce(Integer::sum);
        System.out.println(reduce2.get());
    }


    public static void collectTest() {
        // 将Stream转换List集合
        List<Integer> list2 = list.stream()
                .collect(Collectors.toList());
        System.out.println(list2);

        // 将Stream转换成Set
        // Set:无序、不重复
        Set<Integer> set = list.stream()
                .collect(Collectors.toSet());
        System.out.println(set);
    }
}
